package com.atguigu.dga.governance.assessor.security;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.dga.governance.assessor.Assessor;
import com.atguigu.dga.governance.bean.AssessParam;
import com.atguigu.dga.governance.bean.GovernanceAssessDetail;
import com.atguigu.dga.meta.bean.TableMetaInfo;
import org.apache.commons.lang3.StringUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.math.BigDecimal;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;

@Component("BEYOND_PERMISSION")
public class BeyondPermissionAssessor extends Assessor {
    String filePermission=null;

    String  dirPermission=null;

    @Override
    protected void assessProblem(GovernanceAssessDetail governanceAssessDetail, AssessParam assessParam) throws Exception {
        // 1  遍历表的所有目录 和 文件  用建议权限值  一一比较  只要超过 建议值  给0分

        // 递归：  1  叶子节点处理  返回  2 非叶子节点 下探
        //参考权限
        String metricParamsJson = assessParam.getGovernanceMetric().getMetricParamsJson();
        JSONObject paramJsonObj = JSON.parseObject(metricParamsJson);
          filePermission = paramJsonObj.getString("file_permission");
          dirPermission = paramJsonObj.getString("dir_permission");


        List<String> beyondPermissionPathList= checkPermission(assessParam.getTableMetaInfo() );
        //打分
        if(beyondPermissionPathList.size()>0){
            governanceAssessDetail.setAssessScore(BigDecimal.ZERO);
            governanceAssessDetail.setAssessProblem("存在超过建议权限的目录或文件：["+ StringUtils.join(beyondPermissionPathList,",") +"]");
        }


    }


    //做遍历的准备工作： 起始点 ， 遍历的工具， 记录结果的容器
    private List<String> checkPermission(TableMetaInfo tableMetaInfo ) throws  Exception {
        String tableFsPath = tableMetaInfo.getTableFsPath();
        String owner = tableMetaInfo.getTableFsOwner();
        //HDFS客户端 FileSystem
        FileSystem fileSystem = FileSystem.get(new URI(tableFsPath), new Configuration(), owner);
        FileStatus[] fileStatuses = fileSystem.listStatus(  new Path(tableFsPath));
        List<String> beyondPermissionPathList=new ArrayList<>();
        checkPermissionRec(fileStatuses,fileSystem,beyondPermissionPathList );
        return beyondPermissionPathList;
    }

    private void checkPermissionRec(FileStatus[] fileStatuses,
                                    FileSystem fileSystem,
                                    List<String> beyondPermissionPathList
                                    ) throws  Exception {
        // 递归：  1  叶子节点处理  返回  2 非叶子节点 下探
        for (FileStatus fileStatus : fileStatuses) {
            if(fileStatus.isFile()){
                //用文件的权限和 filePermission进行比较
                boolean beyondPermission = isBeyondPermission(fileStatus, filePermission);
                if(beyondPermission){
                    //如果超过
                    beyondPermissionPathList.add(fileStatus.getPath().toString()) ;
                }

            }else {
                //用目录的权限和 dirPermission进行比较
                boolean beyondPermission = isBeyondPermission(fileStatus, dirPermission);
                if(beyondPermission){
                    //如果超过
                    beyondPermissionPathList.add(fileStatus.getPath().toString()) ;
                }
                //下探
                FileStatus[] subFileStatuses = fileSystem.listStatus(fileStatus.getPath());
                checkPermissionRec(subFileStatuses,fileSystem,beyondPermissionPathList );
            }
        }


    }

    public boolean isBeyondPermission(FileStatus fileStatus,String permission){
        int userPerm = fileStatus.getPermission().getUserAction().ordinal();
        int groupPerm = fileStatus.getPermission().getGroupAction().ordinal();
        int otherPerm = fileStatus.getPermission().getOtherAction().ordinal();

        String userParamPerm = permission.substring(0, 1);
        String groupParamPerm = permission.substring(1, 2);
        String otherParamPerm = permission.substring(2);

        if(userPerm> Integer.valueOf(userParamPerm)
            ||groupPerm> Integer.valueOf(groupParamPerm)
            ||otherPerm> Integer.valueOf(otherParamPerm)){
            return  true;
        }
        return false;

    }



}
